config: clamp ra_mininterval, ra_maxinterval, ra_lifetime at load time
authorPaul Donald <[email protected]>
Fri, 3 Oct 2025 14:34:15 +0000 (16:34 +0200)
committerÁlvaro Fernández Rojas <[email protected]>
Mon, 13 Oct 2025 07:53:02 +0000 (09:53 +0200)
clamp values to RFC defined limits.

First set ra_maxinterval, then ra_mininterval adjusts based on max.

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/225
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/config.c

index 7b0b8fa3bb9f1103a3ad916565cf4b5baf72c83c..fa5e3ef619fd69edbb3c15be14fe8035549781b8 100644 (file)
@@ -1405,14 +1405,50 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
        if ((c = tb[IFACE_ATTR_RA_ADVROUTER]))
                iface->ra_advrouter = blobmsg_get_bool(c);
 
-       if ((c = tb[IFACE_ATTR_RA_MININTERVAL]))
-               iface->ra_mininterval =  blobmsg_get_u32(c);
-
-       if ((c = tb[IFACE_ATTR_RA_MAXINTERVAL]))
-               iface->ra_maxinterval = blobmsg_get_u32(c);
+       /*
+        * RFC4861: MaxRtrAdvInterval: MUST be no less than 4 seconds and no greater than 1800 seconds.
+        * RFC8319: MaxRtrAdvInterval: MUST be no less than 4 seconds and no greater than 65535 seconds.
+        * Default: 600 seconds
+        */
+       if ((c = tb[IFACE_ATTR_RA_MAXINTERVAL])){
+               uint32_t ra_maxinterval = blobmsg_get_u32(c);
+               if (ra_maxinterval < 4)
+                       ra_maxinterval = 4;
+               else if (ra_maxinterval > MaxRtrAdvInterval) 
+                               ra_maxinterval = MaxRtrAdvInterval;
+               iface->ra_maxinterval = ra_maxinterval;
+       }
 
-       if ((c = tb[IFACE_ATTR_RA_LIFETIME]))
-               iface->ra_lifetime = blobmsg_get_u32(c);
+       /*
+        * RFC4861: MinRtrAdvInterval: MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval.
+        * Default: 0.33 * MaxRtrAdvInterval If MaxRtrAdvInterval >= 9 seconds; otherwise, the
+        * Default is MaxRtrAdvInterval.
+        */
+       if ((c = tb[IFACE_ATTR_RA_MININTERVAL])){
+               uint32_t ra_mininterval = blobmsg_get_u32(c);
+               if (ra_mininterval < MinRtrAdvInterval)
+                       ra_mininterval = MinRtrAdvInterval; // clamp min
+               else if (ra_mininterval > (0.75 * (uint32_t)iface->ra_maxinterval)) 
+                               ra_mininterval = 0.75 * (uint32_t)iface->ra_maxinterval; // clamp max
+               iface->ra_mininterval = ra_mininterval;
+       }
+
+       /* 
+        * RFC4861: AdvDefaultLifetime: MUST be either zero or between MaxRtrAdvInterval and 9000 seconds.
+        * RFC8319: AdvDefaultLifetime: MUST be either zero or between MaxRtrAdvInterval and 65535 seconds.
+        * Default: 3 * MaxRtrAdvInterval
+        * i.e. 3 * 65535 => 65535 seconds.
+        */
+       if ((c = tb[IFACE_ATTR_RA_LIFETIME])){
+               uint32_t ra_lifetime = blobmsg_get_u32(c);
+               if (ra_lifetime != 0){
+                       if (ra_lifetime < (uint32_t)iface->ra_maxinterval) 
+                               ra_lifetime = (uint32_t)iface->ra_maxinterval; // clamp min
+                       else if (ra_lifetime > AdvDefaultLifetime)
+                               ra_lifetime = AdvDefaultLifetime; // clamp max
+               }
+               iface->ra_lifetime = ra_lifetime;
+       }
 
        if ((c = tb[IFACE_ATTR_RA_DNS]))
                iface->ra_dns = blobmsg_get_bool(c);